import * as THREE from 'three-legacy';
import { BufferGeometry, LineSegments, Vector3 } from 'three-legacy';
import { ctx2 } from '@app-cad/module';
import { drawTriangular } from '@app-nextmesh/utils';
import { nmAppLog } from '@app-nextmesh/common/utils';
import { refreshCanvas } from './canvas';

// 绘制线和箭头
const arrowChange = (
  centerPoint: number[][],
  length: number,
  max: number,
  min: number,
  value: number[],
  direction: string,
  vector: THREE.Vector3Tuple[][],
  resolvedData: string,
  checked?: string,
) => {
  // 中心数组
  const centers: number[][] = centerPoint; // [[0,0,0], [1, 2, 4]]
  // 中心数组
  // const center = new THREE.Vector3().fromArray(centerPoint); // 中心  [[0,0,0], [1, 2, 4]]
  // 设置箭头头部参数
  const arrowHeadLength =
    direction === 'xx' ||
    direction === 'yy' ||
    direction === 'zz' ||
    direction === 'principal'
      ? length * 2
      : length / 2; // 箭头头部的长度, 负数箭头向外，正数箭头向内

  const positions = [];
  // 绘制箭头材质
  const lineMaterial = new THREE.LineBasicMaterial({
    color: setNormalizationVector(
      direction === 'principal' ? checked : direction,
    ).color,
  });
  nmAppLog('centers----------->:', centers);
  const normalizationVector = setNormalizationVector(direction);
  centers.forEach((center, index) => {
    const directionGroup: {
      fourDrop: Vector3[];
      planeDirection: number[];
      direction: string;
    } = directionPoint(
      direction,
      arrowHeadLength,
      center,
      resolvedData,
      resolvedData === 'elemental' || direction === 'principal'
        ? vector[index]
        : [],
      normalizationVector,
    ); // 获取方向点集合
    // 获取处理所有方向点+中心点
    const dropGroup = directionGroup.fourDrop;
    // const valueMax = Math.abs(max) > Math.abs(min) ? max : min;
    nmAppLog('dropGroup-------------->:', directionGroup, dropGroup);
    positions.push(
      ...drawTensor(
        dropGroup,
        // (value[index] / max) * length, // value值 / 最大 * 长度
        // (Math.abs(value[index]) / Math.abs(valueMax)) * length, // value值 / 最大 * 长度
        length, // value值 / 最大 * 长度
        directionGroup.planeDirection,
        value[index],
        direction,
      ),
    );
  });
  nmAppLog('positions------------>:', positions);
  // 是面片、线或点几何体的有效表述。包括顶点位置，面片索引、法相量、颜色值、UV 坐标和自定义缓存属性值。
  // 使用 BufferGeometry 可以有效减少向 GPU 传输上述数据所需的开销。
  const arrowHeadGeometry = new BufferGeometry().setFromPoints(positions);
  // 在若干对的顶点之间绘制的一系列的线。
  const arrowHead = new LineSegments(arrowHeadGeometry, lineMaterial);
  ctx2.cadScene.toolsGroup.add(arrowHead);
  refreshCanvas();
};

// 设置归一化向量参数以及颜色设置
const setNormalizationVector = (direction: string) => {
  let planeDirection = [];
  let sigmaGlobal = [];
  let color: number = 0xff0000;
  switch (direction) {
    case 'xy':
      sigmaGlobal = [
        [1, 1, 0], //0---
        [0.8, 1, 0], //1…………
        [1, -1, 0], //2;;;
        [1, -0.8, 0], //3---
        [-1, -1, 0], //4。。。。
        [-0.8, -1, 0], //5;;;
        [-1, 1, 0], //6…………
        [-1, 0.8, 0], //7。。。。
      ];
      planeDirection = [0, 0, 1];
      color = 0xffcc00; // 黄
      break;
    case 'xz':
      sigmaGlobal = [
        [1, 0, 1], // 0
        [1, 0, 0.8], //1
        [-1, 0, 1], //2
        [-0.8, 0, 1], //3
        [-1, 0, -1], //4
        [-1, 0, -0.8], //5
        [1, 0, -1], //6
        [0.8, 0, -1], //7
      ];
      planeDirection = [1, 0, 1];
      color = 0xff00ff; // 紫
      break;
    case 'yz':
      sigmaGlobal = [
        [0, 1, 1], // 0
        [0, 1, 0.8], //1
        [0, -1, 1], //2
        [0, -0.8, 1], //3
        [0, -1, -1], //4
        [0, -1, -0.8], //5
        [0, 1, -1], //6
        [0, 0.8, -1], //7
      ];
      planeDirection = [0, 1, 1];
      color = 0x33ffff; //浅蓝
      break;
    case 'xx':
      sigmaGlobal = [
        [1, 0, 0],
        [-1, 0, 0],
      ];
      planeDirection = [0, 1, 0];
      color = 0xff0000; // 红
      break;
    case 'yy':
      sigmaGlobal = [
        [0, 1, 0],
        [0, -1, 0],
      ];
      planeDirection = [1, 0, 0];
      color = 0x33ff66; //绿
      break;
    case 'zz':
      sigmaGlobal = [
        [0, 0, 1],
        [0, 0, -1],
      ];
      color = 0x3399ff; // 深蓝
      planeDirection = [1, 0, 0];
      break;
    case 'principal':
      planeDirection = [0, 0, 1];
      break;
    case 'p1':
      color = 0xff0000; // 红
      break;
    case 'p2':
      color = 0x00ff00; //绿
      break;
    case 'p3':
      color = 0x0000ff; // 深蓝
      break;
  }
  return {
    sigmaGlobal,
    planeDirection,
    color,
  };
};

// 方向点
const directionPoint = (
  direction: string,
  arrowHeadLength: number,
  // vector: THREE.Vector3Tuple[] | number[],
  center: number[],
  resolvedData: string,
  vector?: any,
  normalizationVector?: {
    sigmaGlobal: any[];
    planeDirection: number[];
  },
) => {
  nmAppLog(
    'direction----------->:',
    direction,
    arrowHeadLength,
    vector,
    center,
    normalizationVector,
  );
  // 原点
  const origin = new THREE.Vector3().fromArray(center);
  let fourDrop = [];
  switch (direction) {
    case 'xy':
    case 'xz':
    case 'yz':
      {
        const rotationMatrix = new THREE.Matrix4();
        // 判断渲染是局部坐标
        if (resolvedData === 'elemental') {
          // 已知：x和y求z,x*y=z
          // 已知：y和z求x,y*z=x
          // 已知：z和x求y,x*z=y
          const X = new THREE.Vector3().fromArray(vector[0]);
          const Z = new THREE.Vector3().fromArray(vector[1]);
          const Y = new THREE.Vector3().crossVectors(Z, X);
          // 1. 构建旋转矩阵
          rotationMatrix.set(
            X.x,
            X.y,
            X.z,
            origin.x,
            Y.x,
            Y.y,
            Y.z,
            origin.y,
            Z.x,
            Z.y,
            Z.z,
            origin.z,
            0,
            0,
            0,
            1,
          );
        }

        fourDrop = normalizationVector.sigmaGlobal.map((sigma) => {
          const point = new THREE.Vector3()
            .fromArray(sigma)
            .multiplyScalar(arrowHeadLength / 4);
          nmAppLog('point---------->:', point);
          // 判断渲染局部坐标还是全局坐标
          if (resolvedData === 'global') {
            return point.add(origin);
          } else {
            return point.clone().applyMatrix4(rotationMatrix);
          }
        });
      }
      break;
    case 'xx':
    case 'yy':
    case 'zz':
    case 'principal':
      // 判断渲染是局部坐标
      if (resolvedData === 'elemental' || direction === 'principal') {
        fourDrop = [
          new THREE.Vector3()
            .fromArray(
              direction === 'principal'
                ? [vector[0], vector[1], vector[2]]
                : vector[0],
            )
            .multiplyScalar(arrowHeadLength / 4)
            .add(origin),
          new THREE.Vector3()
            .fromArray(
              direction === 'principal'
                ? [vector[0], vector[1], vector[2]]
                : vector[0],
            )
            .multiplyScalar(arrowHeadLength / 4)
            .negate()
            .add(origin),
        ];
      } else {
        fourDrop = normalizationVector.sigmaGlobal.map((sigma) =>
          new THREE.Vector3()
            .fromArray(sigma)
            .multiplyScalar(arrowHeadLength / 4)
            .add(origin),
        );
      }

      break;
  }
  return {
    fourDrop,
    planeDirection: normalizationVector.planeDirection,
    direction,
  };
};

// 绘制张量图
const drawTensor = (
  arrow: Vector3[], // 结果点
  LineLength: number, // 长度 箭头头部的长度, 负数箭头向外，正数箭头向内
  m: number[], // 面向坐标
  isItPull: number, // 是否是拉力还是压力
  direction: string, // 方向xx,yy,zz,xy,xz,yz
) => {
  // 设置箭头头部参数
  const arrowWidth =
    direction === 'xx' || direction === 'yy' || direction === 'zz'
      ? LineLength / 10
      : direction === 'principal'
        ? LineLength / 20
        : LineLength / 120; // 箭头头部的宽度
  const planeDirection = new THREE.Vector3().fromArray(m); // 箭头面的朝向
  // 长度 箭头头部的长度, 负数箭头向外，正数箭头向内，后端返回的数据正是拉（外），负数是压（内）所以是相反
  const arrowHeadLength =
    isItPull > 0 &&
    (direction === 'xx' ||
      direction === 'yy' ||
      direction === 'zz' ||
      direction === 'principal')
      ? -LineLength
      : direction === 'xx' ||
          direction === 'yy' ||
          direction === 'zz' ||
          direction === 'principal'
        ? LineLength
        : -LineLength / 10;
  return drawLineArrow(
    direction,
    arrow,
    arrowWidth,
    arrowHeadLength,
    planeDirection,
  );
};

// 绘制线和箭头的集合
const drawLineArrow = (
  direction: string, // 方向xx,yy,zz,xy,xz,yz
  arrow: Vector3[], // 结果点
  arrowWidth: number,
  arrowHeadLength: number,
  planeDirection: Vector3,
) => {
  if (direction === 'xy' || direction === 'xz' || direction === 'yz') {
    return [
      ...drawTriangular(
        arrow[0],
        arrow[3],
        arrowWidth,
        arrowHeadLength,
        planeDirection,
      ),
      ...drawTriangular(
        arrow[5],
        arrow[2],
        arrowWidth,
        arrowHeadLength,
        planeDirection,
      ),
      ...drawTriangular(
        arrow[4],
        arrow[7],
        arrowWidth,
        arrowHeadLength,
        planeDirection,
      ),
      ...drawTriangular(
        arrow[1],
        arrow[6],
        arrowWidth,
        arrowHeadLength,
        planeDirection,
      ),
    ];
  } else {
    return [
      ...drawTriangular(
        arrow[0],
        arrow[1],
        arrowWidth,
        arrowHeadLength,
        planeDirection,
      ),
      ...drawTriangular(
        arrow[1],
        arrow[0],
        arrowWidth,
        arrowHeadLength,
        planeDirection,
      ),
    ];
  }
};

export { arrowChange };
